package com.stropheware.droidDefense;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.Log;

import com.stropheware.pathfinding.Node;
import com.stropheware.pathfinding.Path;
import com.stropheware.pathfinding.Path.Step;
import com.stropheware.pathfinding.PathFinder;

public abstract class AbstractEnemy {

	protected Context context;
	protected GameBoard gameBoard;
	private final EnemyManager enemyManager;
	protected int ENEMY_BUFFER_MS = 2 * 1000;
	protected final String TAG = "AbstractEnemy";
	private long startTime = System.currentTimeMillis();
	private long animationStartTime = System.currentTimeMillis();
	private long updateTime = System.currentTimeMillis();
	protected Drawable enemy1;
	protected Drawable enemy2;
	protected Drawable enemy3;
	protected Drawable enemy4;
	

	public AnimationDrawable animationDrawable;
	private int animationCounter = 0;
	public int health;
	protected int maxHealth;
	protected float healthRatio = 1;
	protected Drawable drawable;
	public boolean visible = false;
	public int xPixel;
	public int yPixel;
	protected int nextXpx;
	protected int nextYpx;
	protected double speed;
	protected int animationSpeed;
	protected int reward;
	protected String name;
	protected Timer bufferTimer = new Timer();
	protected Node currentNode = null;
	public ArrayList<Step> currentPathSteps = new ArrayList<Step>();
	protected int currentStep = 0;
	public int addToEnemyPx; //to get to center of enemy
	public int widthPixels;
	protected int numFrames = 2;
	private int numInArray = 0;
	
	//text to draw in pop up
	protected String healthString;
	protected String maxHealthString;
	protected String speedString;
	protected String rewardString;
	static final String NAME_LABEL = "Name: ";
	static final String SPEED_LABEL = "Speed: ";
	static final String REWARD_LABEL = "Reward: ";

	/**size of enemy in terms of cells, e.g. if size == 2 then size is 2x2 cells*/
	public static int SIZE = 3;	
	
	public boolean displayPopUp;

	public AbstractEnemy(Context context, GameBoard gameBoard, EnemyManager enemyManager, int numInArray) {
		this.context = context;
		this.gameBoard = gameBoard;
		this.enemyManager = enemyManager;
		yPixel = 0;
		this.numInArray = numInArray;
		xPixel = 0;
		currentNode = gameBoard.startNode;
		addToEnemyPx = (SIZE / 2)  * gameBoard.cellSideLength;		
		displayPopUp = false;
		enemy1 = context.getResources().getDrawable(R.drawable.enemy1);
		enemy2 = context.getResources().getDrawable(R.drawable.enemy2);
		enemy3 = context.getResources().getDrawable(R.drawable.enemy1);
		enemy4 = context.getResources().getDrawable(R.drawable.enemy2);
		//final
		animationSpeed = 100;
	}
		
	public void updatePath(ArrayList<Step> newPath) {
		currentPathSteps = newPath;
		currentStep = 0;
	}
	
	public void addStepsToPath(ArrayList<Step> newPath) {
		for(int i = 0; i < newPath.size(); i++) {
			currentPathSteps.add(newPath.get(i));
		}
	}
	
	public void hit(int damage) {
		health -= damage;
		if (health <= 0) {
			health = 0;
			visible = false;
			Log.d(TAG, "enemy dead");
			enemyManager.enemyKilled(this);
		}
		healthRatio = (float)health/maxHealth; 
		healthString = ((Integer)health).toString()+"/"+maxHealthString;
	}
	
	public void startAttacking() {
		currentStep = 0;
		findNextStepPixels();
		visible = true;
	}
	
	public void drawDrawable(Canvas canvas) {
		if(visible) {
			updateTime = System.currentTimeMillis();
			if(updateTime - animationStartTime > animationSpeed) {
				updateFrame();	
				animationStartTime = System.currentTimeMillis();
			}
			drawable.setBounds(xPixel, yPixel, xPixel + gameBoard.cellSideLength * SIZE, yPixel + gameBoard.cellSideLength * SIZE);
			drawable.draw(canvas);
		}
	}
	
	/*
	 * speed now defined as # of ticks to move across one cell
	 */
	public void update(int tickCount) {
		if(visible) {
			updateTime = System.currentTimeMillis();
			if(updateTime - startTime > speed) {
				updateCurrentLocation();	
				startTime = System.currentTimeMillis();
			}

		}
	}
	
	private void updateFrame(){
		switch(++animationCounter){
			case 0: drawable = enemy1; return;
			case 1: drawable = enemy2; return;
			case 2: drawable = enemy3; return;
			case 3: drawable = enemy4; return;
			default: animationCounter = -1;
		}

	}
	
	
	private void updateCurrentLocation() {
		if(xPixel == nextXpx && yPixel == nextYpx) {
			currentStep++;
			if(currentStep >= currentPathSteps.size() - 1) {
				visible = false;
				enemyManager.enemyCompletedGoal();
				return;
			}
			findNextStepPixels();
		}
		if(nextXpx > xPixel) xPixel+=1;
		else if(nextXpx < xPixel) xPixel-=1;
		if(nextYpx > yPixel) yPixel+=1;
		else if(nextYpx < yPixel) yPixel-=1;
	}
	
	protected void findNextStepPixels() {
		if(currentStep + 1 < currentPathSteps.size()) {
			Step temp = currentPathSteps.get(currentStep + 1);
			nextXpx = gameBoard.nodes[temp.x][temp.y].occupiedCells[0].pxColumn;
			nextYpx = gameBoard.nodes[temp.x][temp.y].occupiedCells[0].pxRow;
		}
	}
	
	public int getProjectileX() {
		return xPixel + ((SIZE / 2) * gameBoard.cellSideLength);
	}
	
	public int getProjectileY() {
		return yPixel + ((SIZE / 2) * gameBoard.cellSideLength);
	}
	
	public void reset(int delay) {
		xPixel = gameBoard.startCell.pxColumn;
		yPixel = gameBoard.startCell.pxRow;
		health = maxHealth;
		if(delay == 0) startAttacking();
		else {
			bufferTimer.schedule(new EnemyBufferTask(), delay * ENEMY_BUFFER_MS);
		}
	}
	
	class EnemyBufferTask extends TimerTask {
		public void run() {
			startAttacking();
		}
	}
}
